/**
 * Created by Merdan on 2017/2/13.
 */
(function () {
	adminApp.directive('adminTrackedTable', adminTrackedTable);
	adminTrackedTable.$inject = [];
	function adminTrackedTable() {
		return {
			restrict: 'A',
			priority: -1,
			require: 'ngForm',
			controller: adminTrackedTableController
		};
	}
	adminTrackedTableController.$inject = [
		'$scope',
		'$parse',
		'$attrs',
		'$element'
	];
	function adminTrackedTableController($scope, $parse, $attrs, $element) {
		var self = this;
		var tableForm = $element.controller('form');
		var dirtyCellsByRow = [];
		var invalidCellsByRow = [];
		init();
		function init() {
			var setter = $parse($attrs.adminTrackedTable).assign;
			setter($scope, self);
			$scope.$on('$destroy', function () {
				setter(null);
			});
			self.reset = reset;
			self.isCellDirty = isCellDirty;
			self.setCellDirty = setCellDirty;
			self.setCellInvalid = setCellInvalid;
			self.untrack = untrack;
		}
		function getCellsForRow(row, cellsByRow) {
			return _.find(cellsByRow, function (entry) {
				return entry.row === row;
			});
		}
		function isCellDirty(row, cell) {
			var rowCells = getCellsForRow(row, dirtyCellsByRow);
			return rowCells && rowCells.cells.indexOf(cell) !== -1;
		}
		function reset() {
			dirtyCellsByRow = [];
			invalidCellsByRow = [];
			setInvalid(false);
		}
		function setCellDirty(row, cell, isDirty) {
			setCellStatus(row, cell, isDirty, dirtyCellsByRow);
		}
		function setCellInvalid(row, cell, isInvalid) {
			setCellStatus(row, cell, isInvalid, invalidCellsByRow);
			setInvalid(invalidCellsByRow.length > 0);
		}
		function setCellStatus(row, cell, value, cellsByRow) {
			var rowCells = getCellsForRow(row, cellsByRow);
			if (!rowCells && !value) {
				return;
			}
			if (value) {
				if (!rowCells) {
					rowCells = {
						row: row,
						cells: []
					};
					cellsByRow.push(rowCells);
				}
				if (rowCells.cells.indexOf(cell) === -1) {
					rowCells.cells.push(cell);
				}
			} else {
				_.remove(rowCells.cells, function (item) {
					return cell === item;
				});
				if (rowCells.cells.length === 0) {
					_.remove(cellsByRow, function (item) {
						return rowCells === item;
					});
				}
			}
		}
		function setInvalid(isInvalid) {
			self.$invalid = isInvalid;
			self.$valid = !isInvalid;
		}
		function untrack(row) {
			_.remove(invalidCellsByRow, function (item) {
				return item.row === row;
			});
			_.remove(dirtyCellsByRow, function (item) {
				return item.row === row;
			});
			setInvalid(invalidCellsByRow.length > 0);
		}
	}
}());
(function () {
	adminApp.directive('adminTrackedTableRow', adminTrackedTableRow);
	adminTrackedTableRow.$inject = [];
	function adminTrackedTableRow() {
		return {
			restrict: 'A',
			priority: -1,
			require: [
				'^adminTrackedTable',
				'ngForm'
			],
			controller: adminTrackedTableRowController
		};
	}
	adminTrackedTableRowController.$inject = [
		'$attrs',
		'$element',
		'$parse',
		'$scope'
	];
	function adminTrackedTableRowController($attrs, $element, $parse, $scope) {
		var self = this;
		var row = $parse($attrs.adminTrackedTableRow)($scope);
		var rowFormCtrl = $element.controller('form');
		var trackedTableCtrl = $element.controller('adminTrackedTable');
		self.isCellDirty = isCellDirty;
		self.setCellDirty = setCellDirty;
		self.setCellInvalid = setCellInvalid;
		function isCellDirty(cell) {
			return trackedTableCtrl.isCellDirty(row, cell);
		}
		function setCellDirty(cell, isDirty) {
			trackedTableCtrl.setCellDirty(row, cell, isDirty);
		}
		function setCellInvalid(cell, isInvalid) {
			trackedTableCtrl.setCellInvalid(row, cell, isInvalid);
		}
	}
}());
(function () {
	adminApp.directive('adminTrackedTableCell', adminTrackedTableCell);
	adminTrackedTableCell.$inject = [];
	function adminTrackedTableCell() {
		return {
			restrict: 'A',
			priority: -1,
			scope: true,
			require: [
				'^adminTrackedTableRow',
				'ngForm'
			],
			controller: adminTrackedTableCellController
		};
	}
	adminTrackedTableCellController.$inject = [
		'$attrs',
		'$element',
		'$scope'
	];
	function adminTrackedTableCellController($attrs, $element, $scope) {
		var self = this;
		var cellFormCtrl = $element.controller('form');
		var cellName = cellFormCtrl.$name;
		var trackedTableRowCtrl = $element.controller('adminTrackedTableRow');
		if (trackedTableRowCtrl.isCellDirty(cellName)) {
			cellFormCtrl.$setDirty();
		} else {
			cellFormCtrl.$setPristine();
		}
		$scope.$watch(function () {
			return cellFormCtrl.$dirty;
		}, function (newValue, oldValue) {
			if (newValue === oldValue)
				return;
			trackedTableRowCtrl.setCellDirty(cellName, newValue);
		});
		$scope.$watch(function () {
			return cellFormCtrl.$invalid;
		}, function (newValue, oldValue) {
			if (newValue === oldValue)
				return;
			trackedTableRowCtrl.setCellInvalid(cellName, newValue);
		});
	}
}());
(function () {
	adminApp.directive('whenScrolled', whenScrolled);
	whenScrolled.$inject = [];
	function whenScrolled() {
		return function (scope, elm, attr) {
			var raw = elm[0];
			var scrollCompleted = true;
			scope.$on('scrollCompleted', function () {
				scrollCompleted = true;
				console.log('scrollCompleted', scrollCompleted);

			});
			elm.bind('scroll', function () {
				var remainingHeight = raw.offsetHeight - raw.scrollHeight;
				var scrollTop = raw.scrollTop;
				var percent = Math.abs((scrollTop / remainingHeight) * 100);
				if (percent > attr.percent) {
					if (scrollCompleted) {
						scrollCompleted = false;
						scope.$apply(attr.whenScrolled);

					}
				}
			});
		};
	}

}());